package com.topscomm.file.convert.aspose;

import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;

import javax.imageio.ImageIO;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;

import com.aspose.pdf.devices.PngDevice;
import com.aspose.pdf.devices.Resolution;
import com.topscomm.basic.exception.ServiceException;
import com.topscomm.core.FileFormatEnum;
import com.topscomm.file.task.FileProcessProgressCache;
import com.topscomm.file.util.FileUtil;
import com.topscomm.tap.common.ParameterCache;

import lombok.extern.slf4j.Slf4j;

/**
 * 文件转图片
 * 
 * @description:
 * @author: donghang
 * @date: 2021年3月16日下午2:12:06
 * @modify:
 */
@Slf4j
public class AsposeFileConvertToImg {
	/**
	 * 转换文件
	 * 
	 * @description:
	 * @param inputFilePath
	 * @param targetFilePath
	 * @return
	 * @author: donghang
	 * @date: 2021年3月15日下午7:26:46
	 * @modify:
	 */
	public static int fileToImg(String identifier, String inputFilePath, String targetFilePath) throws Exception {
		String mimeType = FileUtil.getMimeType(inputFilePath);
		if (FileUtil.matchMimeType(mimeType, FileFormatEnum.PDF.mimeType)) {
			return pdfToImg(identifier, inputFilePath, targetFilePath, true);
		}
		if (FileUtil.matchMimeType(mimeType, FileFormatEnum.WORD.mimeType)) {
			return wordToImg(identifier, inputFilePath, targetFilePath, true);
		}
		if (FileUtil.matchMimeType(mimeType, FileFormatEnum.EXCEL.mimeType)) {
			return excelToImg(identifier, inputFilePath, targetFilePath, true);
		}
		if (FileUtil.matchMimeType(mimeType, FileFormatEnum.PPT.mimeType)) {
			// return pptToImgByPdf(identifier, inputFilePath, targetFilePath,
			// true);
			return pptToImg(identifier, inputFilePath, targetFilePath, true);
		} else {
			throw new ServiceException("不支持的文件类型");
		}
	}

	/**
	 * 文件转封面
	 * 
	 * @description:
	 * @param inputFilePath
	 * @param targetFilePath
	 * @return
	 * @throws Exception
	 * @author: donghang
	 * @date: 2021年3月30日下午11:34:54
	 * @modify:
	 */
	public static int fileToCoverImg(String identifier, String inputFilePath, String targetFilePath) throws Exception {
		String mimeType = FileUtil.getMimeType(inputFilePath);
		if (FileUtil.matchMimeType(mimeType, FileFormatEnum.PDF.mimeType)) {
			return pdfToImg(identifier, inputFilePath, targetFilePath, false);
		}
		if (FileUtil.matchMimeType(mimeType, FileFormatEnum.WORD.mimeType)) {
			return wordToImg(identifier, inputFilePath, targetFilePath, false);
		}
		if (FileUtil.matchMimeType(mimeType, FileFormatEnum.EXCEL.mimeType)) {
			return excelToImg(identifier, inputFilePath, targetFilePath, false);
		}
		if (FileUtil.matchMimeType(mimeType, FileFormatEnum.PPT.mimeType)) {
			return pptToImg(identifier, inputFilePath, targetFilePath, false);
		} else {
			throw new ServiceException("不支持的文件类型");
		}
	}

	/**
	 * @description: pdf转图片
	 * @param filePath
	 * @param targetPath
	 * @return
	 * @author: wanghongwei
	 * @date: 2021-3-20 9:20:29
	 * @modify:
	 */
	private static int pdfToImg(String identifier, String filePath, String targetPath, boolean isCreateAllPages)
			throws Exception {
		AsposeSetLicense.setPdfAsposeLicense();
		com.aspose.pdf.Document doc = new com.aspose.pdf.Document(filePath);
		int pageCount = 0;
		try {
			pageCount = doc.getPages().size();
			File targetFile = new File(targetPath);
			if (!targetFile.exists()) {
				targetFile.mkdir();
			}
			String fileName = targetPath.substring(targetPath.lastIndexOf("/") + 1) + "_" + pageCount;
			if (isCreateAllPages == false) {
				int maxTitlePages = ParameterCache.getIntValue("FileMaxTitlePages", 6);
				pageCount = pageCount < maxTitlePages ? pageCount : maxTitlePages;
			}
			Resolution resolution = new Resolution(250);
			PngDevice jpegDevice = new PngDevice(resolution);
			for (int i = 1; i <= pageCount; i++) {
				String imageFilePath = targetPath + "/" + fileName + "_" + i + ".png";
				FileOutputStream fileOS = new FileOutputStream(imageFilePath);
				try {
					jpegDevice.process(doc.getPages().get_Item(i), fileOS);
				} catch (Exception e) {
					throw new ServiceException(e);
				} finally {
					if (fileOS != null) {
						fileOS.flush();
						fileOS.close();
					}
				}
				// 更新处理进度
				if (isCreateAllPages == true) {
					FileProcessProgressCache.putValue(identifier, pageCount, i, "");
				}
			}

		} catch (Exception e) {
			throw new ServiceException(e);
		} finally {
			if (doc != null) {
				doc.dispose();
			}
		}
		return pageCount;
	}

	/**
	 * @description: pdf转图片
	 * @param filePath
	 * @param targetPath
	 * @return
	 * @author: wanghongwei
	 * @date: 2021-3-20 9:20:29
	 * @modify:
	 */
	private static int pdfToImgTemp(String identifier, String filePath, String targetPath, boolean isCreateAllPages)
			throws Exception {
		InputStream inputStream = new BufferedInputStream(new FileInputStream(filePath));
		PDDocument pdDocument = PDDocument.load(inputStream);
		PDFRenderer renderer = new PDFRenderer(pdDocument);
		int pageCount = pdDocument.getNumberOfPages();
		File targetFile = new File(targetPath);
		if (!targetFile.exists()) {
			targetFile.mkdir();
		}
		String fileName = targetPath.substring(targetPath.lastIndexOf("/") + 1) + "_" + pageCount;
		// 仅转换封面
		if (isCreateAllPages == false) {
			int maxTitlePages = ParameterCache.getIntValue("FileMaxTitlePages", 6);
			pageCount = pageCount < maxTitlePages ? pageCount : maxTitlePages;
		}
		try {
			for (int i = 0; i < pageCount; i++) {
				String imageFilePath = targetPath + "/" + fileName + "_" + (i + 1) + ".png";
				BufferedImage image = renderer.renderImageWithDPI(i, 150f, ImageType.RGB);
				// 获取缩放后的宽高
				float scale = 1;
				if (image.getWidth() > 2000) {
					scale = 2000 / ((float) image.getWidth());
				}
				int width = (int) (image.getWidth() * scale);
				int height = (int) (image.getHeight() * scale);
				// 调用缩放方法获取缩放后的图片
				Image img = image.getScaledInstance(width, height, Image.SCALE_FAST);
				// 创建一个新的缓存图片
				BufferedImage imageResult = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
				// 获取画笔
				Graphics2D graphics = imageResult.createGraphics();
				// 将Image对象画在画布上,最后一个参数,ImageObserver:接收有关 Image
				// 信息通知的异步更新接口,没用到直接传空
				graphics.drawImage(img, 0, 0, null);
				// 一定要释放资源
				graphics.dispose();

				ImageIO.write(imageResult, "png", new File(imageFilePath));

				// 更新处理进度
				if (isCreateAllPages == true) {
					FileProcessProgressCache.putValue(identifier, pageCount, i + 1, "");
				}
			}
		} catch (Exception e) {
			throw new ServiceException(e);
		} finally {
			if (inputStream != null) {
				inputStream.close();
			}
			if (pdDocument != null) {
				pdDocument.close();
			}
		}
		return pageCount;
	}

	/**
	 * word转图片
	 * 
	 * @description:
	 * @param filePath
	 * @param targetPath
	 * @return
	 * @author: donghang
	 * @throws Exception
	 * @date: 2021年3月15日下午7:01:20
	 * @modify:
	 */
	private static int wordToImg(String identifier, String filePath, String targetPath, boolean isCreateAllPages)
			throws Exception {
		// AsposeSetLicense.setWordAsposeLicense();

		com.aspose.words.Document doc = new com.aspose.words.Document(filePath);
		int pageCount = 0;
		try {
			com.aspose.words.ImageSaveOptions options = new com.aspose.words.ImageSaveOptions(
					com.aspose.words.SaveFormat.PNG);
			options.setResolution(200f);

			pageCount = doc.getPageCount();
			File targetFile = new File(targetPath);
			if (!targetFile.exists()) {
				targetFile.mkdir();
			}
			String fileName = targetPath.substring(targetPath.lastIndexOf("/") + 1) + "_" + pageCount;
			if (isCreateAllPages == false) {
				int maxTitlePages = ParameterCache.getIntValue("FileMaxTitlePages", 6);
				pageCount = pageCount < maxTitlePages ? pageCount : maxTitlePages;
			}
			for (int i = 1; i <= pageCount; i++) {
				options.setPageIndex(i - 1);
				String imageFilePath = targetPath + "/" + fileName + "_" + i + ".png";
				FileOutputStream fileOS = new FileOutputStream(imageFilePath);
				try {
					doc.save(fileOS, options);
				} catch (Exception e) {
					throw new ServiceException(e);
				} finally {
					if (fileOS != null) {
						fileOS.flush();
						fileOS.close();
					}
				}
				// 更新处理进度
				if (isCreateAllPages == true) {
					FileProcessProgressCache.putValue(identifier, pageCount, i, "");
				}
			}

		} catch (Exception e) {
			throw new ServiceException(e);
		} finally {
			if (doc != null) {
				doc.cleanup();
			}
		}
		return pageCount;

	}

	/**
	 * excel转图片
	 * 
	 * @description:
	 * @param filePath
	 * @param targetPath
	 * @return
	 * @author: donghang
	 * @throws Exception
	 * @date: 2021年3月15日下午7:01:41
	 * @modify:
	 */
	private static int excelToImg(String identifier, String filePath, String targetPath, boolean isCreateAllPages)
			throws Exception {
		AsposeSetLicense.setExcelAsposeLicense();
		com.aspose.cells.Workbook workbook = null;
		int pageCount = 0;
		try {
			com.aspose.cells.ImageOrPrintOptions options = new com.aspose.cells.ImageOrPrintOptions();
			// 设置水平分辨率
			options.setHorizontalResolution(150);
			// 设置垂直分辨率
			options.setVerticalResolution(150);
			options.setAllColumnsInOnePagePerSheet(true);
			options.setOnePagePerSheet(false);
			options.setImageFormat(com.aspose.cells.ImageFormat.getPng());
			options.setCellAutoFit(true);
			workbook = new com.aspose.cells.Workbook(filePath);

			File targetFile = new File(targetPath);
			if (!targetFile.exists()) {
				targetFile.mkdir();
			}
			int sheetCount = workbook.getWorksheets().getCount();
			// 计算总数量

			int[] sheetResolution = new int[sheetCount];
			for (int i = 0; i < sheetCount; i++) {
				com.aspose.cells.Worksheet worksheet = workbook.getWorksheets().get(i);
				com.aspose.cells.SheetRender render = new com.aspose.cells.SheetRender(worksheet, options);
				pageCount += render.getPageCount();
				// 修改分辨率，避免内存溢出
				if (render.getPageCount() > 0 && render.getPageSize(0)[0] > 10000) {
					sheetResolution[i] = 100;
				} else {
					sheetResolution[i] = 150;
				}
			}
			String fileName = targetPath.substring(targetPath.lastIndexOf("/") + 1) + "_" + pageCount;
			if (isCreateAllPages == false) {
				int maxTitlePages = ParameterCache.getIntValue("FileMaxTitlePages", 6);
				pageCount = pageCount < maxTitlePages ? pageCount : maxTitlePages;
			}
			int pageNum = 0;
			for (int i = 0; i < sheetCount; i++) {
				com.aspose.cells.Worksheet worksheet = workbook.getWorksheets().get(i);
				// 设置水平分辨率
				options.setHorizontalResolution(sheetResolution[i]);
				// 设置垂直分辨率
				options.setVerticalResolution(sheetResolution[i]);
				com.aspose.cells.SheetRender render = new com.aspose.cells.SheetRender(worksheet, options);
				int curentPageCount = render.getPageCount();
				for (int j = 0; j < curentPageCount; j++) {
					String imageFilePath = targetPath + "/" + fileName + "_" + (++pageNum) + ".png";
					FileOutputStream fileOS = new FileOutputStream(imageFilePath);
					try {
						render.toImage(j, imageFilePath);
					} catch (Exception e) {
						throw new ServiceException(e);
					} finally {
						if (fileOS != null) {
							fileOS.flush();
							fileOS.close();
						}
					}
					// 更新处理进度
					if (isCreateAllPages == true) {
						FileProcessProgressCache.putValue(identifier, pageCount, pageNum, "");
					}
					if (pageNum == pageCount) {
						return pageCount;
					}
				}
			}

		} catch (Exception e) {
			log.error(e.getMessage());
			throw new ServiceException(e);
		} finally {
			if (workbook != null) {
				workbook.dispose();
			}
		}
		return pageCount;
	}

	/**
	 * @description: ppt转图片
	 * @param inputPath
	 * @param targetPath
	 * @return
	 * @author: wanghongwei
	 * @throws Exception
	 * @date: 2021-3-20 8:56:14
	 * @modify:
	 */
	private static int pptToImg(String identifier, String inputPath, String targetPath, boolean isCreateAllPages)
			throws Exception {
		// 只获得封面可以降低文档图片质量
		File targetFile = new File(targetPath);
		if (!targetFile.exists()) {
			targetFile.mkdir();
		}
		// AsposeSetLicense.setPowerPointAsposeLicense();
		com.aspose.slides.Presentation presentation = null;
		int pageCount = 0;
		try {
			presentation = new com.aspose.slides.Presentation(inputPath);
			pageCount = presentation.getSlides().size();
			String fileName = targetPath.substring(targetPath.lastIndexOf("/") + 1) + "_" + pageCount;
			if (isCreateAllPages == false) {
				int maxTitlePages = ParameterCache.getIntValue("FileMaxTitlePages", 6);
				pageCount = pageCount < maxTitlePages ? pageCount : maxTitlePages;
			}
			for (int i = 0; i < pageCount; i++) {
				com.aspose.slides.ISlide slide = presentation.getSlides().get_Item(i);
				int height = (int) (presentation.getSlideSize().getSize().getHeight());
				int width = (int) (presentation.getSlideSize().getSize().getWidth());

				BufferedImage image = slide
						.getThumbnail(new Dimension(2500, (int) (height * ((2500 / (double) width)))));
				String imageFilePath = targetPath + "/" + fileName + "_" + (i + 1) + ".png";
				File outImage = new File(imageFilePath);
				ImageIO.write(image, "png", outImage);
				// 更新处理进度
				if (isCreateAllPages == true) {
					FileProcessProgressCache.putValue(identifier, pageCount, i + 1, "");
				}
			}

		} catch (Exception e) {
			log.error(e.getMessage());
			throw new ServiceException(e);
		} finally {
			if (presentation != null) {
				presentation.dispose();
			}
		}
		return pageCount;

	}

	/**
	 * ppt转图片，先转pdf
	 * 
	 * @description:
	 * @param identifier
	 * @param inputPath
	 * @param targetPath
	 * @param isCreateAllPages
	 * @return
	 * @throws Exception
	 * @author: donghang
	 * @date: 2021年5月15日下午6:49:21
	 * @modify:
	 */
	private static int pptToImgByPdf(String identifier, String inputPath, String targetPath, boolean isCreateAllPages)
			throws Exception {

		if (isCreateAllPages) {
			// 先将ppt转pdf，再将pdf转图片,直接ppt转图片会有不清晰问题
			String pdfFilePath = AsposeFileConvertToPdf.fileToPdf(identifier, inputPath, targetPath);
			return AsposeFileConvertToImg.pdfToImg(identifier, pdfFilePath, targetPath, isCreateAllPages);
		} else {
			// 只获得封面可以降低文档图片质量
			File targetFile = new File(targetPath);
			if (!targetFile.exists()) {
				targetFile.mkdir();
			}
			AsposeSetLicense.setPowerPointAsposeLicense();
			com.aspose.slides.Presentation presentation = new com.aspose.slides.Presentation(inputPath);
			int pageCount = presentation.getSlides().size();
			int maxTitlePages = ParameterCache.getIntValue("FileMaxTitlePages", 6);
			pageCount = pageCount < maxTitlePages ? pageCount : maxTitlePages;
			String fileName = targetPath.substring(targetPath.lastIndexOf("/") + 1) + "_" + pageCount;
			for (int i = 0; i < pageCount; i++) {
				com.aspose.slides.ISlide slide = presentation.getSlides().get_Item(i);
				int height = (int) (presentation.getSlideSize().getSize().getHeight());
				int width = (int) (presentation.getSlideSize().getSize().getWidth());
				BufferedImage image = slide.getThumbnail(new Dimension(width, height));
				String imageFilePath = targetPath + "/" + fileName + "_" + (i + 1) + ".png";
				File outImage = new File(imageFilePath);
				ImageIO.write(image, "png", outImage);
			}
			return pageCount;
		}
	}
}
